package io.mft.commons.ioc;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;

import cn.hutool.core.util.ObjectUtil;
/**
 * 接口api注册处理器
 * @类型名称：MapperRegistryProcessor
 * @说明：TODO
 * @创建者: 胡常建  
 * @创建时间: 2018年3月9日 上午7:25:45
 * @修改者: 胡常建  
 * @修改时间: 2018年3月9日 上午7:25:45
 */
/*@Component   AutowiredAnnotationBeanPostProcessor */  
public class MFTSpringRegistryProcessor implements BeanDefinitionRegistryPostProcessor,BeanPostProcessor {
	private static Map<ClassLoader, MFTBasePackageProvider> providerMap=new ConcurrentHashMap<ClassLoader, MFTSpringRegistryProcessor.MFTBasePackageProvider>();
	public static void registerContextClassLoaderMFTBasePackageProvider(MFTBasePackageProvider provider) {
		ClassLoader classLoader=Thread.currentThread().getContextClassLoader();
		registerContextClassLoaderMFTBasePackageProvider(classLoader, provider);
	}
	public static void registerContextClassLoaderMFTBasePackageProvider(ClassLoader classLoader,MFTBasePackageProvider provider) {
		providerMap.put(classLoader, provider);
	}
	/**
	 * 扫描包提供处理器
	 * @说明：TODO
	 * @类型名称：MFTBasePackageProvider
	 * @创建者: 胡常建  
	 * @创建时间: 2021年2月26日 上午10:53:06
	 * @修改者: 胡常建  
	 * @修改时间: 2021年2月26日 上午10:53:06
	 */
	public interface MFTBasePackageProvider{
		List<MFTBasePackage> provid();
	}
	private static Set<String> commonBasePackages=new HashSet<>();
	private static Set<String> commonScanPackages=new HashSet<>();
	public static void registerCommonBasePackages(String ...packages) {
		commonBasePackages.addAll(Arrays.asList(packages));
	}
	public static void registerCommonScanPackages(String ...packages) {
		commonScanPackages.addAll(Arrays.asList(packages));
	}
	private Set<String> basePackages;
	private Set<String> scanPackages;
	Logger logger=LoggerFactory.getLogger(MFTSpringRegistryProcessor.class);
	public Set<String> getBasePackages() {
		return basePackages;
	}
	public Set<String> getScanPackages() {
		return scanPackages;
	}
	public void setScanPackages(Set<String> scanPackages) {
		this.scanPackages = scanPackages;
	}
	public void setBasePackages(Set<String> basePackages) {
		this.basePackages = basePackages;
	}
	public MFTSpringRegistryProcessor() {
	}
	
	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

	}
	
	private List<MFTBasePackage> parseMFTBasePackage(Set<String> packages) {
		List<MFTBasePackage> mftBasePackages=new ArrayList<MFTBasePackage>();
		if (ObjectUtil.isNotNull(packages)) {
			for (String t : packages) {
				 String[] arr=t.split("-");
				 String sysNo=arr[0];
				 String basePackage=arr[1];
				 MFTBasePackage mftBasePackage=new MFTBasePackage();
				 mftBasePackage.setBasePackage(basePackage);
				 mftBasePackage.setSysNo(sysNo);
				 mftBasePackages.add(mftBasePackage);
			}
		}
		return mftBasePackages;
	}
	
	private Map<String, MFTBasePackage> scanPackages() {
		List<MFTBasePackage> mftBasePackages=parseMFTBasePackage(this.scanPackages);
		ClassLoader classLoader=Thread.currentThread().getContextClassLoader();
		MFTBasePackageProvider provider=providerMap.get(classLoader);
		if (provider!=null) {
			List<MFTBasePackage> providemMftBasePackages=provider.provid();
			if (providemMftBasePackages!=null) {
				mftBasePackages.addAll(providemMftBasePackages);
			}
		}
		List<MFTBasePackage> commonsPackages=parseMFTBasePackage(commonScanPackages);
		mftBasePackages.addAll(commonsPackages);
		Map<String, MFTBasePackage> map=new HashMap<String, MFTBasePackage>();
		for (MFTBasePackage mftBasePackage : mftBasePackages) {
			map.put(mftBasePackage.id(), mftBasePackage);
		}
		return map;
	}
	
	private Map<String, MFTBasePackage> basePackages() {
		List<MFTBasePackage> basePackages=parseMFTBasePackage(this.basePackages);
		List<MFTBasePackage> commonsPackages=parseMFTBasePackage(commonBasePackages);
		basePackages.addAll(commonsPackages);
		Map<String, MFTBasePackage> map=new HashMap<String, MFTBasePackage>();
		for (MFTBasePackage mftBasePackage : basePackages) {
			map.put(mftBasePackage.id(), mftBasePackage);
		}
		return map;
	}
	@Override
	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
		try {
			Map<String, MFTBasePackage> basePackageMap=basePackages();
			Map<String, MFTBasePackage> scanPackageMap=scanPackages();
			List<MFTBasePackage> scanPackageList=new ArrayList<>(scanPackageMap.values());
			for (MFTBasePackage mftBasePackage : basePackageMap.values()) {
				 SpringIocRegistryScanner scanner=new SpringIocRegistryScanner(mftBasePackage.getSysNo(),mftBasePackage.getBasePackage());
				 scanner.scanAndRegistry(registry, scanPackageList);
			}
		} catch (Exception e) {
			logger.error("", e);
		}
	}
	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		for (BeanBeforeInitializationProcessor<?> initializationProcessor : BeanBeforeInitializationProcessorRegistry.getProcessors()) {
			 if (initializationProcessor.isConditionClass(bean.getClass())) {
				 initializationProcessor.invokeProcess(bean, beanName);
			}
		}
		return bean;
	}
	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

}
